#include "ustc_comdef.h"
#include "ustc_custom.h"
#include "ustc_hif.h"
#include "ustc_api.h"
#include "ustc_usb_drv.h"
#include "ustc_usb_scsi.h"
#include "ustc_usb_bulk.h"
#include "ustc_usb_chap9.h"

extern USB_PATH_T *gp_usb_path;

/*===========================================================================
FUNCTION:  usb_init_hw

DESCRIPTION  
	initilize usb module hardware
	
INPUT PARAMETER
	NONE
OUTPUT PARAMETER  
	NONE
RETURN VALUE
	NONE

===========================================================================*/
USTC_U32 value;

void usb_init_hw(void)
{
	//clear int
	USTC_IO_OUTW(USB_INT_STATUS,0x0);
	USTC_IO_OUTB(APP_INTR,0);
	//set int mask
	USTC_IO_OUTW(USB_INT_MASK,(INT_APP_INTR|INT_TX_ACK|INT_TX_NAK|INT_RX_DISCARD|INT_RX_VALID|INT_NEED_RESET));
	USTC_IO_OUTB(APP_IMASK,(USTC_U8)~(APP_INT_SETUP));//|APP_INT_IN|APP_INT_OUT|APP_INT_ACK));

	//set power on;
	USTC_IO_OUTW(USB_PWR_INDT,1);
	//set ep0 active
	USTC_IO_OUTBM(APP_EP0_STATUS, ACTIVE,ACTIVE);

}

/*===========================================================================
FUNCTION:  usb_deinit_hw

DESCRIPTION  
	disable interrupt and  clock
	//restore DMA global mux register; and disable clock
	
INPUT PARAMETER
	NONE
OUTPUT PARAMETER  
	NONE
RETURN VALUE
	NONE

===========================================================================*/
void usb_deinit_hw(void)
{

	//clear int mask; powe down; endpoint set to inactive
	USTC_IO_OUTW(USB_INT_MASK,0);
	USTC_IO_OUTB(APP_IMASK,0xff);//|APP_INT_IN|APP_INT_OUT|APP_INT_ACK));
//	USTC_IO_OUTW(USB_PWR_INDT,0);

	usb_stall_ep(0,0);
	usb_stall_ep(2,0);
	usb_stall_ep(3,0);

	usb_active_ep(0,0);
	usb_active_ep(2,0);
	usb_active_ep(3,0);

}

USTC_U16 usb_write_ep(USTC_U8 endp,unsigned char*buff,unsigned short len)
{
	USTC_U8	slen,i;
	USTC_U32 *p=(USTC_U32*)buff;

	gp_usb_path->in_tx = 1;
	gp_usb_path->ep_buff_retry = buff;
	gp_usb_path->ep_tx_len = len;
	
	slen = len/4;
	if (len %4)
		slen++;
	//clear fifo
	USTC_IO_OUTWM(USB_TX_STATUS,TX_FIFO_CLEAR,TX_FIFO_CLEAR);
	USTC_IO_OUTWM(USB_TX_STATUS,TX_FIFO_CLEAR,0);

#if 0
	for (i=0;i<slen;i++)
	{
		USTC_IO_OUTW(USB_FIFO_TX,*((USTC_U32 *)buff+i));
	}	
#else
	for (i=0; i<slen/8; i++)
	{
		ustc_io_burst_outw(USB_FIFO_TX, p);
		p+=8;
	}

	for (i=0; i<slen%8; i++)
		ustc_io_outw(USB_FIFO_TX, p[i]);
#endif

	if (endp ==0)//cotnrol
	{
		//tx packet ready
		USTC_IO_OUTWM(USB_TX_STATUS, TX_EP0_READY|TX_LEN,TX_EP0_READY| (len<<4));
	}
	else
	{
		//tx packet ready
		USTC_IO_OUTWM(USB_TX_STATUS, TX_EP1_READY|TX_LEN,TX_EP1_READY| (len<<4));
	}	

	return RSP_SUCCESS;
	
}


/*===========================================================================
FUNCTION:  usb_read_ep

DESCRIPTION 
	configure hardware and software to be ready to receive data from Host;
	after OUT token, HW transfer received data to our buffer;and notify software via INT
	
INPUT PARAMETER
	endp: endpoint index, 0 for control endpoint; 1 for  bulk out endpoint
	buff:  buffer contain the data to send to host(should be DWORD align)
OUTPUT PARAMETER  
	 NULL
RETURN VALUE
	RSP_SUCCESS,                Good status 
	USB_FAIL_S,                  failed  
	USB_MEM_ALLOCATE_FAIL_S	memory fail
NOTE:
	the buffer should be released after Tx Complete

===========================================================================*/
USTC_U16 usb_read_ep(USTC_U8 endp,USTC_U8 *buff)
{
	if (endp ==0)//cotnrol
	{
		//ready to receive
		USTC_IO_OUTW(USB_RX_STATUS, RX_EP0_READY);
			
	}
	else//bulk in
	{
		//ready to receive
		USTC_IO_OUTW(USB_RX_STATUS, RX_EP1_READY);
	}

	//ENABLE RX INT
	USTC_IO_OUTWM(USB_INT_MASK,INT_RX_DISCARD|INT_RX_VALID,(INT_RX_DISCARD|INT_RX_VALID));
	
	return RSP_SUCCESS;
	
}

/*===========================================================================
FUNCTION:  usb_stall_ep0

DESCRIPTION 
	set cotnrol endpoint to STALL state
	
INPUT PARAMETER
	NONE
OUTPUT PARAMETER  
	 NONE
RETURN VALUE
	NULL
===========================================================================*/
void usb_stall_ep(USTC_U8 endp,USTC_U8 bStalled)
{
	USTC_U8	val;
	if (bStalled)
		val = PSTALL;
	else
		val =0;
	if (endp==0 || endp==1)
	{
		USTC_IO_OUTBM(APP_EP0_STATUS, PSTALL,val);
	}
	else if (endp==2)
	{
		USTC_IO_OUTBM(APP_EP2_STATUS,PSTALL,val);
	}
	else if (endp==3)
	{
		USTC_IO_OUTBM(APP_EP3_STATUS,PSTALL,val);
	}
	
}

//active all endpoint
void usb_active_ep(USTC_U8 endp ,USTC_U8 active)
{
	USTC_U8 val;
	if (active)
		val = (USTC_U8)ACTIVE;
	else
		val = 0;
	if (endp==0 || endp==1)
	{
		USTC_IO_OUTBM(APP_EP0_STATUS, ACTIVE,val);
	}
	else if (endp==2)
	{
		USTC_IO_OUTBM(APP_EP2_STATUS, ACTIVE,val);
	}
	else if (endp==3)
	{
		USTC_IO_OUTBM(APP_EP3_STATUS, ACTIVE,val);
	}
}

USTC_U8 usb_get_ep_status(USTC_U8 endp)
{
	if(endp ==0)
		return USTC_IO_INB(APP_EP0_STATUS);
	else if (endp==1)
		return USTC_IO_INB(APP_EP0_STATUS);
	else if (endp==2)
		return USTC_IO_INB(APP_EP2_STATUS);
	else if (endp==3)
		return USTC_IO_INB(APP_EP3_STATUS);
	return 0;
}

void usb_set_cfg(USTC_U8 value)
{
	USTC_IO_OUTB(APP_CFG_VALUE,value);
}

void usb_set_ccomp(USTC_U8 value)
{
	USTC_U8	val;
	if (value)
		val = CCOMP;
	else
		val =0;
	//set CCOMP of ep_info(READ-MODIFY-WRITE)
	USTC_IO_OUTW(USB_LOCK_CTL,1);
	USTC_IO_OUTBM(APP_EP0_STATUS,CCOMP,val);
	USTC_IO_OUTW(USB_LOCK_CTL,0);

}
